﻿using System;
using System.Collections.Generic;

namespace Roborally.Spelleider
{
    /// <summary>
    /// Een instantie van deze klasse representeert een Deck van kaarten (met het type IKaart)
    /// </summary>
    /// <typeparam name="T">Het type kaart voor dit dek</typeparam>
    public class Deck<T> where T : CommonData.GlobaleTypes.IProgramKaart
    {
        #region Fields en Properties
        private List<T> kaarten;
        public List<T> Kaarten { get { return kaarten; } }
        #endregion

        /// <summary>
        /// interne constructor. maakt een nieuw deck aan.
        /// </summary>
        private Deck()
        {
            kaarten = new List<T>();
        }


        /// <summary>
        /// Voegt een kaart toe aan het deck
        /// </summary>
        /// <param name="t">kaart</param>
        public bool AddKaart(T t)
        {
            if (typeof(T) == typeof(CommonData.GlobaleTypes.IProgramKaart))
            {
                return false;
            }
            foreach (T kaart in kaarten)
            {
                if (kaart.Equals(t))
                    return false;
            }
            addKaart(t);
            return false;
        }

        private void addKaart(T t)
        {
            kaarten.Add(t);
        }

        /// <summary>
        /// Verwijdert kaart uit lijst.
        /// </summary>
        /// <param name="t">de geselecteerde kaart</param>
        private void removeKaart(T t)
        {
            kaarten.Remove(t);
        }

        /// <summary>
        /// Maakt een nieuw programdeck aan met alle programkaarten er in.
        /// </summary>
        /// <returns>Een Deck met het type ProgramKaart</returns>
        public static Deck<CommonData.GlobaleTypes.IProgramKaart> ProgramDeck()
        {
            Deck<CommonData.GlobaleTypes.IProgramKaart> deck = new Deck<CommonData.GlobaleTypes.IProgramKaart>();
            foreach (CommonData.Enums.KaartSoort type in Enum.GetValues(typeof(CommonData.Enums.KaartSoort)))
            {
                switch (type)
                {
                    case CommonData.Enums.KaartSoort.Backup:
                        for (int i = 0; i < 6; i++)
                            deck.addKaart(new CommonData.GlobaleTypes.ProgramKaart(type, i * 10 + 430, 1));
                        break;
                    case CommonData.Enums.KaartSoort.Uturn:
                        for (int i = 0; i < 6; i++)
                            deck.addKaart(new CommonData.GlobaleTypes.ProgramKaart(type, i * 10 + 10));
                        break;
                    case CommonData.Enums.KaartSoort.Vooruit:
                        for (int i = 0; i < 18; i++)
                            deck.addKaart(new CommonData.GlobaleTypes.ProgramKaart(type, i * 10 + 490, 1));
                        for (int i = 0; i < 12; i++)
                            deck.addKaart(new CommonData.GlobaleTypes.ProgramKaart(type, i * 10 + 670, 2));
                        for (int i = 0; i < 6; i++)
                            deck.addKaart(new CommonData.GlobaleTypes.ProgramKaart(type, i * 10 + 790, 3));
                        break;
                    case CommonData.Enums.KaartSoort.LinksDraaien:
                        for (int i = 0; i < 18; i++)
                            deck.addKaart(new CommonData.GlobaleTypes.ProgramKaart(type, i * 20 + 70));
                        break;
                    case CommonData.Enums.KaartSoort.RechtsDraaien:
                        for (int i = 0; i < 18; i++)
                            deck.addKaart(new CommonData.GlobaleTypes.ProgramKaart(type, i * 20 + 80));
                        break;
                    default:
                        break;
                }
            }

            return deck;
        }

        /// <summary>
        /// deck samenstellen zonder bepaalde kaarten.
        /// </summary>
        /// <param name="uitgesloten">kaarten die niet in deck moeten zitten</param>
        /// <returns></returns>
        public static Deck<CommonData.GlobaleTypes.IProgramKaart> ProgramDeckZonder(List<CommonData.GlobaleTypes.IProgramKaart> uitgesloten)
        {
            Deck<CommonData.GlobaleTypes.IProgramKaart> deck = ProgramDeck();
            foreach (CommonData.GlobaleTypes.IProgramKaart kaart in uitgesloten)
                deck.removeKaart(kaart);
            return deck;
        }

        //Twan Wolthof - 0910740wolthof
        //KAPOT geen klasse OptieKaart
        //Zolang geen andert component deze method gebruikt wordt deze uitgecomment.
        /*
        /// <summary>
        /// Maakt een nieuw optiedeck aan met alle optiekaarten er in.
        /// </summary>
        /// <returns>Een Deck met het type ProgramKaart</returns>
        public static Deck<OptieKaart> OptieDeck()
        {
            Deck<OptieKaart> deck = new Deck<OptieKaart>();
            foreach (OptieKaart.Soort type in Enum.GetValues(typeof(OptieKaart.Soort)))
            {
                deck.addKaart(new OptieKaart(type));
            }
            return deck;
        }*/


        /// <summary>
        /// schud de kaarten.
        /// </summary>
        public void Schudden()
        {
            List<T> geschud = new List<T>();
            Random r = new Random();
            while (kaarten.Count > 0)
            {
                int rand = r.Next(kaarten.Count);
                T kaart = kaarten[rand];
                kaarten.RemoveAt(rand);
                geschud.Add(kaart);
            }
            kaarten = geschud;
        }

        /// <summary>
        /// aantal kaarten uit deck verwijderen.
        /// </summary>
        /// <param name="aantal">geeft aan hoeveel kaarten er gepakt mogen worden.</param>
        /// <returns></returns>
        public List<T> Pakken(int aantal)
        {
            List<T> geven = new List<T>();
            while (aantal > 0 && kaarten.Count > 0)
            {
                T kaart = kaarten[0];
                kaarten.RemoveAt(0);
                geven.Add(kaart);
                aantal--;
            }
            return geven;
        }
    }
}
